#pragma once

#include <vector>
#include <iostream>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cassert>

namespace CH //CudaHelper
{
	template <class T>
	class ConstantMemory
	{
	public:
		static void Create(const char* device_symbol_name,  const std::vector<T>& host_constant)
		{
			cudaError_t e = cudaMemcpyToSymbol(device_symbol_name, &host_constant[0], sizeof(T)*host_constant.size(), 0, cudaMemcpyHostToDevice);
			assert(e == cudaSuccess);
		}

		static void Create(const char* device_symbol_name,  const T* host_constant, const size_t& size)
		{
			cudaError_t e = cudaMemcpyToSymbol(device_symbol_name, host_constant, size*sizeof(T), 0, cudaMemcpyHostToDevice);
			assert(e == cudaSuccess);
		}

		static void Create(const char* device_symbol_name,  const T& host_constant)
		{
			cudaError_t e = cudaMemcpyToSymbol(device_symbol_name, &host_constant, sizeof(T), 0, cudaMemcpyHostToDevice);
			assert(e == cudaSuccess);
		}
	};

	template<class T>
	void CreateConstantMemory(const char* device_symbol_name, const std::vector<T>& host_constant)
	{
		ConstantMemory<T>::Create(device_symbol_name, host_constant);
	}

	template<class T>
	void CreateConstantMemory(const char* device_symbol_name, const T* host_constant, const size_t& size)
	{
		ConstantMemory<T>::Create(device_symbol_name, host_constant, size);
	}

	template<class T>
	void CreateConstantMemory(const char* device_symbol_name, const T& host_constant)
	{
		ConstantMemory<T>::Create(device_symbol_name, host_constant);
	}

}